package com.meida.module.arc.provider.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.security.OpenUser;
import com.meida.common.utils.ApiAssert;
import com.meida.module.arc.client.constants.ArchiveConstants;
import com.meida.module.arc.client.entity.ArcCategorySecond;
import com.meida.module.arc.client.entity.ArcSecondField;
import com.meida.module.arc.client.enums.CategorySecondEnum;
import com.meida.module.arc.client.utils.ArcUtils;
import com.meida.module.arc.provider.mapper.ArcCategorySecondMapper;
import com.meida.module.arc.provider.service.ArcCategorySecondService;
import com.meida.module.arc.provider.service.ArcSecondFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 二级分类接口实现类
 *
 * @author flyme
 * @date 2022-08-07
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ArcCategorySecondServiceImpl extends BaseServiceImpl<ArcCategorySecondMapper, ArcCategorySecond> implements ArcCategorySecondService {

    @Autowired
    private ArcSecondFieldService arcSecondFieldService;

    private String genSysCode(Long parentId){
        String parentSysCode = null;
        //1查询父节点sysCode
        if(!ArchiveConstants.ROOT_PARENT_ID.equals(parentId)&&FlymeUtils.isNotEmpty(parentId)){
            ArcCategorySecond dict = getById(parentId);
            parentSysCode = dict.getSysCode();
        }
        //2查询子节点最大sysCode
        CriteriaQuery<ArcCategorySecond> query = new CriteriaQuery<ArcCategorySecond>(ArcCategorySecond.class);
        query.lambda().eq(ArcCategorySecond::getParentId,parentId);
        query.orderByDesc("sysCode");
        query.limit(1);
        ArcCategorySecond preSysCodeObj = getOne(query);
        if(preSysCodeObj==null){
            return ArcUtils.genNextSysCode(parentSysCode,null);
        }else{
            return ArcUtils.genNextSysCode(parentSysCode,preSysCodeObj.getSysCode());
        }
    }

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ArcCategorySecond acs, EntityMap extra) {
        ApiAssert.isNotEmpty("参数不能为空",acs);
        ApiAssert.isNotEmpty("全宗id不能为空",acs.getQzId());
        ApiAssert.isNotEmpty("父id不能为空",acs .getParentId());
        Integer type = acs.getType();
        ApiAssert.isNotEmpty("二级分类类型不能为空",type);
        if(CategorySecondEnum.getValue(type)==null){
            ApiAssert.failure("二级分类类型只能为0或1");
        }
        ApiAssert.isNotEmpty("二级分类名称不能为空",acs.getCnName());
        if(!ArchiveConstants.ROOT_PARENT_ID.equals(acs.getParentId())){
            ArcCategorySecond dict = getById(acs.getParentId());
            ApiAssert.isNotEmpty("父id不存在",dict);
        }
        acs.setSysCode(genSysCode(acs.getParentId()));
        //生成序号
        CriteriaQuery<ArcCategorySecond> query = new CriteriaQuery<ArcCategorySecond>(ArcCategorySecond.class);
        query.eq("parentId",acs.getParentId());
        query.orderByDesc("seq");
        query.limit(1);
        ArcCategorySecond obj = this.baseMapper.selectOne(query);
        if(FlymeUtils.isEmpty(obj)){
            acs.setSeq(0);
        }else{
            acs.setSeq(obj.getSeq()+1);
        }
        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, ArcCategorySecond arcCategorySecond, EntityMap extra) {
        loadData2Redis();
        return ResultBody.ok("保存成功", arcCategorySecond);
    }

    @Override
    public ResultBody upOrDown(Map var1) {
        ApiAssert.isNotEmpty("二级分类id不能为空",var1.get("categorySecondId"));
        ApiAssert.isNotEmpty("移动类型不能为空",var1.get("type"));
        //排序为从小到大排   type为1为上移  2为下移
        Long categorySecondId = NumberUtil.parseLong(var1.get("categorySecondId")+"");
        Integer type = NumberUtil.parseInt(var1.get("type")+"");
        if(type!=1&&type!=2){
            ApiAssert.failure("移动类型只能为上移或下移");
        }
        ArcCategorySecond cate = this.getById(categorySecondId);
        CriteriaQuery<ArcCategorySecond> query = new CriteriaQuery<ArcCategorySecond>(ArcCategorySecond.class);
        query.lambda().eq(ArcCategorySecond::getParentId,cate.getParentId());//查询同级别的
        query.orderByAsc("seq");//基于seq从大到小排序
        List<ArcCategorySecond> list = this.list(query);
        int sourceIndex = -1;
        int targetIndex = -1;
        for(int i=0;i<list.size();i++){
            ArcCategorySecond obj = list.get(i);
            if(obj.getCategorySecondId().equals(categorySecondId)){
                if(type==1){//上移
                    if(i==0){
                        return ResultBody.failed("无法上移");
                    }else{
                        sourceIndex = i;
                        targetIndex = i-1;
                    }
                }else if(type==2){//下移
                    if(i==list.size()-1){
                        return ResultBody.failed("无法下移");
                    }else{
                        sourceIndex = i;
                        targetIndex = i+1;
                    }
                }
            }
        }
        if(sourceIndex<0||targetIndex<0){
            return ResultBody.failed("移动错误");
        }
        Long targetId = list.get(sourceIndex).getCategorySecondId();
        list.get(sourceIndex).setCategorySecondId(list.get(targetIndex).getCategorySecondId());
        list.get(targetIndex).setCategorySecondId(targetId);
        List<ArcCategorySecond> updateObj = new ArrayList<>();
        for(int i=0;i<list.size();i++){
            ArcCategorySecond obj = new ArcCategorySecond();
            obj.setCategorySecondId(list.get(i).getCategorySecondId());
            obj.setSeq(i);
            updateObj.add(obj);
        }
        this.saveOrUpdateBatch(updateObj);
        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<ArcCategorySecond> cu, ArcCategorySecond t, EntityMap extra) {
        ApiAssert.isNotEmpty("二级门类id不能为空",t.getCategorySecondId());
        OpenUser user = OpenHelper.getUser();
        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<ArcCategorySecond> cd) {
        ApiAssert.isNotEmpty("二级门类id不能为空",cd.getIdValue());
        LambdaQueryWrapper<ArcSecondField> lambdaQueryWrapper = new LambdaQueryWrapper<ArcSecondField>();
        lambdaQueryWrapper.eq(ArcSecondField::getCategorySecondId,cd.getIdValue());

        this.arcSecondFieldService.remove(lambdaQueryWrapper);

        return ResultBody.ok();
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Long[] ids) {
        loadData2Redis();

        return super.afterDelete(cd, ids);
    }

    @Override
    public ResultBody afterEdit(CriteriaUpdate cu, ArcCategorySecond arcCategorySecond, EntityMap extra) {
        loadData2Redis();
        return ResultBody.ok("更新成功", arcCategorySecond);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ArcCategorySecond> cq, ArcCategorySecond acs, EntityMap requestMap) {
        cq.eq("parentId");
        cq.eq("qzId");
          cq.orderByAsc("acs.seq");
          return ResultBody.ok();
    }

    @Override
    public ResultBody beforeListEntityMap(CriteriaQuery<ArcCategorySecond> cq, ArcCategorySecond t, EntityMap requestMap) {
        ApiAssert.isNotEmpty("参数不能为空",t);
        ApiAssert.isNotEmpty("全宗id不能为空",t.getQzId());
        ApiAssert.isNotEmpty("门类id不能为空",t.getCategoryId());
        cq.eq("parentId");
        cq.eq("qzId");
        cq.eq("categoryId");
        return ResultBody.ok();
    }

    @Override
    public ResultBody list4Redis(Map params) {

        ArcCategorySecond t = BeanUtil.toBean(params, ArcCategorySecond.class);
        ApiAssert.isNotEmpty("参数不能为空", t);
        ApiAssert.isNotEmpty("全宗id不能为空", t.getQzId());
        ApiAssert.isNotEmpty("门类id不能为空", t.getCategoryId());

        List<ArcCategorySecond> list = redisUtils.getList(ArchiveConstants.ARC_CATEGORY_SECOND_PREFIX);
        if (CollUtil.isEmpty(list)) {
            loadData2Redis();
            list = redisUtils.getList(ArchiveConstants.ARC_CATEGORY_SECOND_PREFIX);
        }
        List<ArcCategorySecond> collect = list.stream().filter(a -> a.getQzId().equals(t.getQzId()) && a.getCategoryId().equals(t.getCategoryId())).collect(Collectors.toList());
        if (ObjectUtil.isNotNull(t.getParentId())) {
            List<ArcCategorySecond> collect1 = collect.stream().filter(a -> a.getParentId().equals(t.getParentId())).collect(Collectors.toList());
            return ResultBody.ok(collect1);
        }

        return ResultBody.ok(collect);
    }

    synchronized void loadData2Redis() {
        if (redisUtils.hasKey(ArchiveConstants.ARC_CATEGORY_SECOND_PREFIX)) {
            redisUtils.del(ArchiveConstants.ARC_CATEGORY_SECOND_PREFIX);
        }
        //List<ArcCategorySecond> list = this.list();
        //redisUtils.setList(ArchiveConstants.ARC_CATEGORY_SECOND_PREFIX,list);
    }
}
